package org.slusk.thynwor.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;

public class ResultsLog2Csv {

	public static final String identifier = "INFO: #SASAS# ";
	
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		
		String inputFile = args[0];
		String outputFile = args[1];
		
		// Read lines from file into "Rows" list
		LinkedList<Row> list = buildRowsListFromFile(inputFile);
				
		// Dump the list to a csv, including aggregate data
		dumpToCsv(outputFile, list);
	}

	/**
	 * @param inputFile
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	protected static LinkedList<Row> buildRowsListFromFile(String inputFile) throws FileNotFoundException, IOException {
		String line;
		Row row; 
		LinkedList<Row> list = new LinkedList<Row>();
		
		// Open file for reading.
		BufferedReader in = new BufferedReader(new FileReader(inputFile));
		
		// for each line in the file:
		while ((line = in.readLine()) != null) {
			// If the line starts with "INFO: #SASAS# "
			if (line.startsWith(identifier)) {
				// Make a string out of the remainder
				line = line.substring(identifier.length()).trim();
				
				// Build a Row out of the string
				row = stringToRow(line);
	
				// add the Row to the list
				list.add(row);
			}
		}
		
		// close that file
		in.close();
		
		return list;
	}

	private static Row stringToRow(String line) {
		// split that on commas
		String[] tokens = line.split(",");
		
		// make a new Row
		Row row = new Row();
		
		// now for each token, split on '=', assign the 'values' to the field in the Row.
		row.run 			= tokens[0].split("=")[1];
		row.successful		= tokens[1].split("=")[1];
		row.bestIndividual	= tokens[2].split("=")[1];
		row.foodCollected	= tokens[3].split("=")[1];
		row.gen 			= tokens[4].split("=")[1];
		
		return row;
	}

	private static void dumpToCsv(String outputFile, LinkedList<Row> list) throws IOException {
		// open file for writing
		BufferedWriter out = new BufferedWriter(new FileWriter(outputFile));
		
		// get header from Row, output to file
		out.write(getCsvHeader());
		out.newLine();
		
		// for each Row in the list
		for (Row row : list) {
			// get csv output string from row, output to file.
			out.write(row.getCsvLine());
			out.newLine();
		}
		
		// Build Aggregates String
		String aggString = buildAggregatesString(list);

		// write aggregates string to file
		out.newLine();
		out.write(aggString);
		out.newLine();
		
		// close the file
		out.close();
	}
	

	public static String getCsvHeader() {
		return "Run#,Successful?,BestIndividual,BestFoodCollected,GenerationOfBest";
	}

	private static String buildAggregatesString(LinkedList<Row> list) {
		StringBuilder sb = new StringBuilder();
		LinkedList<Row> successfulList = new LinkedList<Row>();
		int solvedCount = 0;
		int lowestGen = Integer.MAX_VALUE;
		double bestFood = 0;
		int gen; 
		double food;
		
		// Add count - straight forward
		sb.append("Count,");
		sb.append(list.size());
		sb.append("\n");
		
		double foodTotal = 0;
		// iterate list, tracking variables...
		for (Row row : list) {
			// solved count
			//if (Boolean.parseBoolean(row.successful)) {
				solvedCount++;
				// adding solved Rows to list for averaging generation
				successfulList.add(row);
				gen = Integer.parseInt(row.gen);
				// minimum gen - the lowest best gen that was successful
				if (gen < lowestGen) lowestGen = gen;
			//}

			// maximum food - the highest food collected
			food = Double.parseDouble(row.foodCollected);
			if (food > bestFood) bestFood = food;
			foodTotal += food;
		}
		
		// Calculate generation average from successful list
		double generationAverage = averageGenerations(successfulList);
		
		// calculate solved percent
		double solvedPercent = (double) solvedCount / list.size();
		
		double foodAvg = (double) foodTotal / list.size();
		
		// put these in a string
		sb.append("SolvedPercent,");
		sb.append(solvedPercent);
		sb.append("\n");
		sb.append("GenerationAverage,");
		sb.append(generationAverage);
		sb.append("\n");
		sb.append("LowestGeneration,");
		sb.append(lowestGen);
		sb.append("\n");
		sb.append("BestFood,");
		sb.append(bestFood);
		sb.append("\n");
		sb.append("FoodAvg,");
		sb.append(foodAvg);
		sb.append("\n");
		
		return sb.toString();
	}

	private static double averageGenerations(LinkedList<Row> successfulList) {
		double total = 0;
		for (Row row : successfulList) {
			total += Double.parseDouble(row.gen);
		}
		
		return total/(double)successfulList.size();
	}
	
}


class Row {
	protected String run;
	protected String successful;
	protected String bestIndividual;
	protected String foodCollected;
	protected String gen;
	
	public String getCsvLine() {
		return run + "," + successful + "," + bestIndividual + "," + foodCollected + "," + gen;
	}
}